package com.lucy.vd.disk;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.lucy.disk.controller.DiskTransferController;
import com.lucy.disk.entity.FileEntity;
import com.lucy.disk.params.FileUploadParams;
import com.lucy.disk.service.DiskFileService;
import com.lucy.disk.service.StorageService;
import com.lucy.starter.constant.HttpStatus;
import com.lucy.starter.domain.ResponseDTO;
import com.lucy.starter.exception.BusinessException;
import com.lucy.vd.constant.ViewerDiskConst;
import com.lucy.viewer.params.ViewerFile;
import com.lucy.viewer.service.ViewerFileService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

/**
 * @author kindear
 * lucy-disk 提供 viewer 文件相关服务
 */
@Slf4j
@Service
@AllArgsConstructor
public class DiskViewerFileServiceImpl implements ViewerFileService {
    DiskFileService fileService;

    StorageService storageService;

    DiskTransferController diskTransferCtl;


    // 返回可访问地址
    @Override
    public String fileUpload(MultipartFile file) {
        FileUploadParams params = new FileUploadParams();
        params.setFile(file);
        // @TODO 不同文件桶分配规则
        params.setBucketName(ViewerDiskConst.BUCKET);
        try {
            ResponseDTO<Object> responseDTO = diskTransferCtl.fileUpload(params);
            FileEntity res = (FileEntity) responseDTO.getData();
            return "/disk/download/" + res.getId();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    @SneakyThrows
    public ViewerFile createCustomViewerFile(ViewerFile viewerFile) {
        // 获取文件流
        String filePath = viewerFile.getPath();
        // 获取文件名
        String fileName = viewerFile.getFileName();

        InputStream stream = FileUtil.getInputStream(filePath);
        // 构建参数
        MultipartFile file = new MultipartFile() {
            @Override
            public String getName() {
                return fileName;
            }

            @Override
            public String getOriginalFilename() {
                return fileName;
            }

            @Override
            public String getContentType() {
                return "application/octet-stream";
            }

            @Override
            public boolean isEmpty() {
                return false;
            }

            @Override
            public long getSize() {
                try {
                    return stream.available();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public byte[] getBytes()  {
                return IoUtil.readBytes(stream);
            }

            @Override
            public InputStream getInputStream()  {
                return stream;
            }

            @Override
            public void transferTo(File dest)  {
                FileUtil.writeFromStream(stream,dest);
            }
        };
        FileUploadParams params = new FileUploadParams();
        params.setFile(file);
        params.setBucketName(ViewerDiskConst.BUCKET);
        try {
            ResponseDTO<Object> responseDTO = diskTransferCtl.fileUpload(params);
            FileEntity res = (FileEntity) responseDTO.getData();
            // 构建 key
            viewerFile.setKey(res.getId());
            log.info("新建文件key:{}",res.getId());
            // 构建 url
            viewerFile.setUrl("/disk/download/" + res.getId());
            // 设置
            viewerFile.setPath("");
            // 返回
            log.info("文件创建成功");
            return viewerFile;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public InputStream getCustomViewerFileStream(String s) {
        Optional<FileEntity> fileOp = fileService.getOne(s);
        if (!fileOp.isPresent()) return null;
        FileEntity file = fileOp.get();

        // 判断文件状态
        if (file.getStatus().equals(0)){
            throw new BusinessException(HttpStatus.FORBIDDEN,"文件禁止访问");
        }

        String fileName = file.getId() + "." + file.getExtName();
        try {
            return storageService.downloadFile(file.getBucketName(),fileName);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public ViewerFile getCustomViewerFile(String s) {
        Optional<FileEntity> fileOp = fileService.getOne(s);
        if (!fileOp.isPresent()) return null;
        FileEntity file = fileOp.get();
        // 构建返回结果
        return buildViewerFile(file);
    }

    @Override
    public ViewerFile updateCustomViewerFile(InputStream inputStream, String s) {
        Optional<FileEntity> fileOp = fileService.getOne(s);
        if (!fileOp.isPresent()) return null;
        FileEntity file = fileOp.get();

        // 判断文件状态
        if (file.getStatus().equals(0)){
            throw new BusinessException(HttpStatus.FORBIDDEN,"文件禁止访问");
        }

        // 构建文件
        ViewerFile viewerFile = buildViewerFile(file);
            // 获取文件在存储桶中的名称
            String fileKey = viewerFile.getKey() + "." + viewerFile.getFileType();
            // 更新文件
            try {
                // 获取默认
                String bucketName = ViewerDiskConst.BUCKET;
                storageService.updateFile(inputStream, bucketName, fileKey);
                return viewerFile;
            } catch (Exception e) {
                throw new RuntimeException(e);
        }
    }

    ViewerFile buildViewerFile(FileEntity file){
        ViewerFile viewerFile = new ViewerFile();
        viewerFile.setKey(file.getId());
        viewerFile.setFileName(file.getFileName());
        viewerFile.setTitle(file.getFileName());
        viewerFile.setFileType(file.getExtName());
        viewerFile.setMd5(file.getMd5());
        viewerFile.setUrl("/disk/download/"+file.getId());
        return viewerFile;
    }
}
